﻿#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <filesystem>
#include <vector>

namespace fs = std::filesystem;

// 读取配置文件并返回键值对映射
std::unordered_map<std::string, std::string> readConfigFile(const std::string& configFilePath) {
    std::ifstream configFile(configFilePath);
    if (!configFile.is_open()) {
        throw std::runtime_error("无法打开配置文件: " + configFilePath);
    }

    std::unordered_map<std::string, std::string> configMap;
    std::string line;
    while (std::getline(configFile, line)) {
        size_t delimiterPos = line.find('=');
        if (delimiterPos != std::string::npos) {
            std::string key = line.substr(0, delimiterPos);
            std::string value = line.substr(delimiterPos + 1);
            configMap[key] = value;
        }
    }

    return configMap;
}

// 替换文件内容中的键值对
void replaceInFile(const std::string& filePath, const std::unordered_map<std::string, std::string>& replacements, int &bChanged) {
    std::ifstream inputFile(filePath);
    if (!inputFile.is_open()) {
        throw std::runtime_error("无法打开文件: " + filePath);
    }

    bChanged = 0;
    std::ostringstream oss;
    std::string line;
    while (std::getline(inputFile, line)) {
        for (const auto&[key, value] : replacements) {
            size_t pos = 0;
            while ((pos = line.find(key, pos)) != std::string::npos) {
                ++bChanged;
                line.replace(pos, key.length(), value);
                pos += value.length();
            }
        }
        oss << line << "\n";
    }

    inputFile.close();

    std::ofstream outputFile(filePath);
    if (!outputFile.is_open()) {
        throw std::runtime_error("无法写入文件: " + filePath);
    }

    outputFile << oss.str();
    outputFile.close();
}

// 遍历目录并替换符合条件的文件内容
void processDirectory(const std::string& directoryPath, const std::unordered_map<std::string, std::string>& replacements, const std::vector<std::string>& extensions) {
    for (const auto& entry : fs::recursive_directory_iterator(directoryPath)) {
        if (entry.is_regular_file()) {
            std::string path = entry.path().string();
            std::string extension = path.substr(path.find_last_of(".") + 1);

            if (std::find(extensions.begin(), extensions.end(), extension) != extensions.end()) {
                try {
                    int bChanged = 0;
                    replaceInFile(path, replacements, bChanged);
                    if (bChanged > 0)
                    {
                        std::cout << "已处理文件: " << path << " ======= Changed num:"<< bChanged << std::endl;
                    }
                }
                catch (const std::exception& e) {
                    std::cerr << "处理文件时出错: " << path << " - " << e.what() << std::endl;
                }
            }
        }
    }
}

int main(int argc, char* argv[]) {
    if (argc < 4) {
        std::cerr << "用法: " << argv[0] << " <配置文件路径> <目录路径> <文件扩展名1> [<文件扩展名2> ...]\nconfig.ini d:/tmp/base-test h cpp hh cc" << std::endl;
        return 1;
    }

    std::string configFilePath = argv[1];
    std::string directoryPath = argv[2];

    std::vector<std::string> extensions;
    for (int i = 3; i < argc; ++i) {
        extensions.push_back(argv[i]);
    }

    try {
        std::unordered_map<std::string, std::string> replacements = readConfigFile(configFilePath);
        processDirectory(directoryPath, replacements, extensions);
    }
    catch (const std::exception& e) {
        std::cerr << "程序运行时出错: " << e.what() << std::endl;
        return 1;
    }

    system("pause");
    return 0;
}



